/* 
 * File:   Engine.h
 * Author: Gab'z
 *
 * Created on 27 mai 2012, 20:04
 */

#ifndef ENGINE_H
#define	ENGINE_H

#include "CalculatorParser.h"
#include "CommandManager.h"
#include "../model/Context.h"
#include "../model/parameters/Parameters.h"
#include "../view/CalculatorMainWindow.h"
#include "log/LogSystem.h"
#include <string>

namespace calculator {

    /**
     * Moteur principal de l'application.
     * Initialisé à partir du contexte, il fait le lien entre la vue et le modèle.
     * Aucun paramètre n'est enregistré dans cette couche de l'application.
     * Les méthodes d'appel direct de commandes de cette classe permettent d'éviter
     * l'affichage du nom de la commande dans la ligne de saisie après son exécution.
     */
    class Engine {
    public:
        /**
         * Constructeur de Engine.
         * 
         * Référence un unique contexte, et initialise le parseur 
         * et le gestionnaire de commandes de l'application.
         * @param context le contexte courant de l'application, il n'est pas 
         * possible d'en changer pendant l'exécution du programme.
         * 
         */
        Engine(Context * const context);

        /**
         * Destructeur de Engine.
         * Libère le parseur et le gestionnaire de commandes.
         */
        virtual ~Engine();

        /**
         * getter Context.
         * @return Le contexte courant, il peut être modifié, 
         * mais ne peut pas être remplacé.
         */
        const Context * const getContext() const;

        /**
         * Méthode centrale de l'application.
         * Lit le texte dans la ligne de saisie par défaut et lance l'exécution
         * du moteur, si aucu n argument, une chaine vide est utilisée par défaut
         * et conduit à la Commande DUP.
         * @param byPassCommand Une commande passée directement depuis un bouton de l'interface.
         */
        void run(std::string byPassCommand = "") const;

        /**
         * Appel direct de la commande DROP.
         * @see run()
         */
        void drop() const;

        /**
         * Appel direct de la commande UNDO.
         * @see run()
         */
        void undo() const;

        /**
         * Appel direct de la commande REDO.
         * @see run()
         */
        void redo() const;

        /**
         * Appel direct de la commande SNEW.
         * @see run()
         */
        void newStack() const;

        /**
         * Appel direct de la commande SDUP.
         * @see run()
         */
        void dupStack() const;

        /**
         * Appel direct de la commande SREM.
         * @see run()
         */
        void removeCurrentStack() const;

        /**
         * Modifie le type de constante utilisé par l'application.
         * @param constantType le type de constante souhaité sous la forme d'une string.
         * @see ConstantType
         */
        void setConstantTypeTo(const std::string& constantType) const;

        /**
         * Modifie l'unité de l'angle utilisée par l'application.
         * @param angleUnit le type de constante souhaité sous la forme d'une string.
         * @see AngleUnit
         */
        void setAngleUnitTo(const std::string& angleUnit) const;

        /**
         * Active ou désactive le mode complexe.
         */
        void switchComplexMode() const;

        /**
         * Utilisation via l'interface des paramètres, permet de sauvegarder les 
         * paramètres après validation.
         * @param parameters les paramètres à sauvegarder.
         */
        void saveAllParameters(const Parameters* parameters) const;

        /**
         * Utilisation lors d'un clic sur un onglet.
         * Modifie l'itérateur pointant vers la pile courante du contexte.
         * @param index désigne la nouvelle pile courante
         */
        void setCurrentStack(int index) const;

        /**
         * Utilisation par l'interface pour mettre à jour la ligne de saisie du contexte.
         * Engine travaille avec cette copie et non directement avec la QInputLine de l'interface.
         * @param str le texte à placer dans la ligne de saisie du contexte.
         */
        void setInputText(const std::string& str) const;

    private:
        /**
         * Pointeur vers le contexte courant.
         * Ne peut pas être remplacé.
         */
        Context * const _context;

        /**
         * Pointeur vers le parseur utilisé par le moteur de la calculatrice.
         * Le parseur est détruit automatiquement à la fermeture de l'application.
         * Ne peut pas être remplacé.
         */

        CalculatorParser * const _calculatorParser;
        /**
         * Pointeur vers le gestionnaire de commandes utilisé par le moteur de la calculatrice.
         * Le gestionnaire de commandes est détruit automatiquement à la fermeture de l'application.
         * Ne peut pas être remplacé.
         */
        CommandManager * const _commandManager;

        static Logger* log;
    };
}

#endif	/* ENGINE_H */

